package config

import (
	"fmt"
	"os"
	"path/filepath"
	"time"

	"gopkg.in/yaml.v3"
)

// Config 主配置结构
type Config struct {
	Global    GlobalConfig       `yaml:"global"`
	Processes []ProcessConfig    `yaml:"processes,omitempty"` // 保留字段但标记为可选，实际从 configs/processes/ 加载
	Logging   LoggingConfig      `yaml:"logging"`
	Notify    NotificationConfig `yaml:"notify"`
}

// ProcessConfigFile 单个进程配置文件结构
type ProcessConfigFile struct {
	Process ProcessConfig `yaml:"process"`
}

// GlobalConfig 全局配置
type GlobalConfig struct {
	CheckInterval time.Duration `yaml:"check_interval"`
	Timeout       time.Duration `yaml:"timeout"`
	RetryCount    int           `yaml:"retry_count"`
	RetryDelay    time.Duration `yaml:"retry_delay"`
	ServerID      string        `yaml:"server_id"` // 自定义服务器标识
}

// ProcessConfig 进程监控配置
type ProcessConfig struct {
	Name          string        `yaml:"name"`
	PID           int32         `yaml:"pid,omitempty"`
	Command       string        `yaml:"command,omitempty"`
	AutoRestart   bool          `yaml:"auto_restart"`
	RestartCmd    string        `yaml:"restart_cmd,omitempty"`
	WorkDir       string        `yaml:"work_dir,omitempty"`
	Env           []string      `yaml:"env,omitempty"`
	CheckInterval time.Duration `yaml:"check_interval,omitempty"`
	Enabled       bool          `yaml:"enabled"`
	// 进程组相关配置
	IsGroup      bool     `yaml:"is_group,omitempty"`      // 是否为进程组
	GroupPattern string   `yaml:"group_pattern,omitempty"` // 进程组模式，如 "DEMO%d" 表示 DEMO1, DEMO2, ...
	GroupStart   int      `yaml:"group_start,omitempty"`   // 起始编号
	GroupEnd     int      `yaml:"group_end,omitempty"`     // 结束编号
	GroupMembers []string `yaml:"group_members,omitempty"` // 手动指定的组成员
	// 资源阈值配置
	ResourceLimits *ResourceLimits `yaml:"resource_limits,omitempty"`
	// 退出码配置
	ExitCodeConfig *ExitCodeConfig `yaml:"exit_code_config,omitempty"`
}

// ResourceLimits 资源限制配置
type ResourceLimits struct {
	MaxCPUPercent    float64       `yaml:"max_cpu_percent,omitempty"`    // 最大CPU使用率
	MaxMemoryPercent float64       `yaml:"max_memory_percent,omitempty"` // 最大内存使用率
	MaxMemoryMB      int64         `yaml:"max_memory_mb,omitempty"`      // 最大内存使用量(MB)
	CheckInterval    time.Duration `yaml:"check_interval,omitempty"`     // 资源检查间隔
}

// ExitCodeConfig 退出码配置
type ExitCodeConfig struct {
	RestartOnExitCodes   []int `yaml:"restart_on_exit_codes,omitempty"`    // 需要重启的退出码列表
	NoRestartOnExitCodes []int `yaml:"no_restart_on_exit_codes,omitempty"` // 不需要重启的退出码列表
	DefaultRestart       bool  `yaml:"default_restart"`                    // 默认是否重启
}

// LoggingConfig 日志配置
type LoggingConfig struct {
	Level      string `yaml:"level"`  // debug, info, warn, error
	Format     string `yaml:"format"` // json, text
	Output     string `yaml:"output"` // stdout, file
	FilePath   string `yaml:"file_path,omitempty"`
	MaxSize    int    `yaml:"max_size"` // MB
	MaxBackups int    `yaml:"max_backups"`
	MaxAge     int    `yaml:"max_age"` // days
}

// NotificationConfig 通知配置
type NotificationConfig struct {
	Enabled bool         `yaml:"enabled"`
	Feishu  FeishuConfig `yaml:"feishu"`
}

// FeishuConfig 飞书配置
type FeishuConfig struct {
	WebhookURL  string                      `yaml:"webhook_url"`
	Secret      string                      `yaml:"secret,omitempty"`
	Enabled     bool                        `yaml:"enabled"`
	UseCard     bool                        `yaml:"use_card"`        // 是否使用卡片消息
	SmartNotify bool                        `yaml:"smart_notify"`    // 是否启用智能通知
	Rules       map[string]NotificationRule `yaml:"rules,omitempty"` // 智能通知规则
}

// NotificationRule 通知规则
type NotificationRule struct {
	MessageType    string        `yaml:"message_type"`    // 消息类型
	MinInterval    time.Duration `yaml:"min_interval"`    // 最小通知间隔
	MaxFrequency   int           `yaml:"max_frequency"`   // 最大通知频率（每小时）
	QuietHours     []TimeRange   `yaml:"quiet_hours"`     // 静默时间
	EscalationTime time.Duration `yaml:"escalation_time"` // 升级时间
	Enabled        bool          `yaml:"enabled"`         // 是否启用
}

// TimeRange 时间范围
type TimeRange struct {
	Start string `yaml:"start"` // 格式: "HH:MM"
	End   string `yaml:"end"`   // 格式: "HH:MM"
}

// LoadConfig 加载配置文件
func LoadConfig(configPath string) (*Config, error) {
	// 检查配置文件是否存在
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		return nil, fmt.Errorf("配置文件不存在: %s", configPath)
	}

	// 读取配置文件
	data, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("读取配置文件失败: %v", err)
	}

	// 解析YAML
	var config Config
	if err := yaml.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("解析配置文件失败: %v", err)
	}

	// 只从 configs/processes/ 目录加载进程配置
	processesDir := filepath.Join(filepath.Dir(configPath), "processes")
	processConfigs, err := LoadProcessConfigs(processesDir)
	if err != nil {
		return nil, fmt.Errorf("加载进程配置文件失败: %v", err)
	}

	// 直接使用从文件加载的进程配置（忽略 config.yaml 中的 processes 字段）
	config.Processes = processConfigs

	// 检查是否至少有一个进程配置
	if len(config.Processes) == 0 {
		return nil, fmt.Errorf("至少需要配置一个进程（请在 configs/processes/ 目录中添加进程配置文件）")
	}

	// 设置默认值
	setDefaults(&config)

	// 验证配置
	if err := validateConfig(&config); err != nil {
		return nil, fmt.Errorf("配置验证失败: %v", err)
	}

	return &config, nil
}

// setDefaults 设置默认值
func setDefaults(config *Config) {
	// 全局配置默认值
	if config.Global.CheckInterval == 0 {
		config.Global.CheckInterval = 30 * time.Second
	}
	if config.Global.Timeout == 0 {
		config.Global.Timeout = 10 * time.Second
	}
	if config.Global.RetryCount == 0 {
		config.Global.RetryCount = 3
	}
	if config.Global.RetryDelay == 0 {
		config.Global.RetryDelay = 5 * time.Second
	}

	// 进程配置默认值
	for i := range config.Processes {
		if config.Processes[i].CheckInterval == 0 {
			config.Processes[i].CheckInterval = config.Global.CheckInterval
		}
		// 如果Enabled字段未设置（零值），则默认为true
		// 但不要覆盖用户明确设置的false值
	}

	// 日志配置默认值
	if config.Logging.Level == "" {
		config.Logging.Level = "info"
	}
	if config.Logging.Format == "" {
		config.Logging.Format = "text"
	}
	if config.Logging.Output == "" {
		config.Logging.Output = "stdout"
	}
	if config.Logging.MaxSize == 0 {
		config.Logging.MaxSize = 100
	}
	if config.Logging.MaxBackups == 0 {
		config.Logging.MaxBackups = 3
	}
	if config.Logging.MaxAge == 0 {
		config.Logging.MaxAge = 7
	}
}

// GetEnabledProcesses 获取启用的进程配置
func (c *Config) GetEnabledProcesses() []ProcessConfig {
	var enabled []ProcessConfig
	for _, proc := range c.Processes {
		if proc.Enabled {
			enabled = append(enabled, proc)
		}
	}
	return enabled
}

// SaveConfig 保存配置到文件
func SaveConfig(config *Config, configPath string) error {
	data, err := yaml.Marshal(config)
	if err != nil {
		return fmt.Errorf("序列化配置失败: %v", err)
	}

	if err := os.WriteFile(configPath, data, 0644); err != nil {
		return fmt.Errorf("保存配置文件失败: %v", err)
	}

	return nil
}

// validateConfig 验证配置
func validateConfig(config *Config) error {
	// 验证全局配置
	if err := validateGlobalConfig(&config.Global); err != nil {
		return fmt.Errorf("全局配置验证失败: %v", err)
	}

	// 验证进程配置
	if err := validateProcessConfigs(config.Processes); err != nil {
		return fmt.Errorf("进程配置验证失败: %v", err)
	}

	// 验证日志配置
	if err := validateLoggingConfig(&config.Logging); err != nil {
		return fmt.Errorf("日志配置验证失败: %v", err)
	}

	// 验证通知配置
	if err := validateNotificationConfig(&config.Notify); err != nil {
		return fmt.Errorf("通知配置验证失败: %v", err)
	}

	return nil
}

// validateGlobalConfig 验证全局配置
func validateGlobalConfig(global *GlobalConfig) error {
	if global.CheckInterval <= 0 {
		return fmt.Errorf("检查间隔必须大于0")
	}
	if global.Timeout <= 0 {
		return fmt.Errorf("超时时间必须大于0")
	}
	if global.RetryCount < 0 {
		return fmt.Errorf("重试次数不能为负数")
	}
	if global.RetryDelay < 0 {
		return fmt.Errorf("重试延迟不能为负数")
	}
	return nil
}

// validateProcessConfigs 验证进程配置
func validateProcessConfigs(processes []ProcessConfig) error {
	// 允许进程列表为空（可以只在 configs/processes/ 目录中配置）
	if len(processes) == 0 {
		return nil
	}

	processNames := make(map[string]bool)
	for i, proc := range processes {
		// 检查进程名称
		if proc.Name == "" {
			return fmt.Errorf("进程 %d: 进程名称不能为空", i+1)
		}

		// 检查进程名称重复
		if processNames[proc.Name] {
			return fmt.Errorf("进程名称重复: %s", proc.Name)
		}
		processNames[proc.Name] = true

		// 验证单个进程配置
		if err := validateSingleProcessConfig(&proc); err != nil {
			return fmt.Errorf("进程 %s 配置错误: %v", proc.Name, err)
		}
	}

	return nil
}

// validateSingleProcessConfig 验证单个进程配置
func validateSingleProcessConfig(proc *ProcessConfig) error {
	// 检查工作目录
	if proc.WorkDir != "" {
		// 工作目录可以是相对路径或绝对路径，这里只检查基本格式
		if len(proc.WorkDir) > 1000 {
			return fmt.Errorf("工作目录路径过长")
		}
	}

	// 检查重启命令
	if proc.AutoRestart && proc.RestartCmd == "" {
		return fmt.Errorf("启用自动重启时必须配置重启命令")
	}

	// 检查进程组配置
	if proc.IsGroup {
		if proc.GroupPattern == "" && len(proc.GroupMembers) == 0 {
			return fmt.Errorf("进程组必须配置模式或成员列表")
		}
		if proc.GroupPattern != "" && (proc.GroupStart <= 0 || proc.GroupEnd <= 0) {
			return fmt.Errorf("使用模式时必须配置起始和结束数字")
		}
		if proc.GroupStart > proc.GroupEnd {
			return fmt.Errorf("起始数字不能大于结束数字")
		}
	}

	// 检查资源限制
	if proc.ResourceLimits != nil {
		if proc.ResourceLimits.MaxCPUPercent < 0 || proc.ResourceLimits.MaxCPUPercent > 100 {
			return fmt.Errorf("CPU使用率限制必须在0-100之间")
		}
		if proc.ResourceLimits.MaxMemoryPercent < 0 || proc.ResourceLimits.MaxMemoryPercent > 100 {
			return fmt.Errorf("内存使用率限制必须在0-100之间")
		}
		if proc.ResourceLimits.MaxMemoryMB < 0 {
			return fmt.Errorf("内存限制不能为负数")
		}
	}

	return nil
}

// validateLoggingConfig 验证日志配置
func validateLoggingConfig(logging *LoggingConfig) error {
	validLevels := map[string]bool{
		"debug": true, "info": true, "warn": true, "error": true,
	}
	if !validLevels[logging.Level] {
		return fmt.Errorf("无效的日志级别: %s", logging.Level)
	}

	validFormats := map[string]bool{
		"text": true, "json": true,
	}
	if !validFormats[logging.Format] {
		return fmt.Errorf("无效的日志格式: %s", logging.Format)
	}

	validOutputs := map[string]bool{
		"stdout": true, "file": true,
	}
	if !validOutputs[logging.Output] {
		return fmt.Errorf("无效的日志输出: %s", logging.Output)
	}

	if logging.MaxSize <= 0 {
		return fmt.Errorf("日志文件最大大小必须大于0")
	}
	if logging.MaxBackups < 0 {
		return fmt.Errorf("日志备份数量不能为负数")
	}
	if logging.MaxAge < 0 {
		return fmt.Errorf("日志保留天数不能为负数")
	}

	return nil
}

// validateNotificationConfig 验证通知配置
func validateNotificationConfig(notify *NotificationConfig) error {
	if !notify.Enabled {
		return nil // 通知未启用时跳过验证
	}

	// 验证飞书配置
	if notify.Feishu.Enabled {
		if notify.Feishu.WebhookURL == "" {
			return fmt.Errorf("飞书通知启用时必须配置Webhook URL")
		}
		if len(notify.Feishu.WebhookURL) < 10 {
			return fmt.Errorf("飞书Webhook URL格式不正确")
		}
	}

	return nil
}
